/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997-2009 Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Sam Lantinga
    slouken@libsdl.org
*/

#include "../SDL_cellvideo.h"
#include "../../../joystick/SDL_joystick_c.h"
#include <cell/pad.h>

/* Data */
static const uint32_t			AxisIndex[4] = {6, 7, 4, 5};

/* Helpers */
static void						ProcessJoystickButton				(SDL_Joystick* aJoystick, uint32_t aIndex, uint32_t aButton, uint32_t aNew, uint32_t aOld)
{
	/* Bail early */
	if(aIndex >= NUM_PADS || !CELL_Video.Pads.Pads[aIndex].Open || aButton >= NUM_BUTTONS || CELL_Video.Pads.ButtonMap[aButton].Nullify || (aNew == aOld))
	{
		return;
	}

	/* If the button is now down */
	if(aNew && !(CELL_Video.Pads.ButtonMap[aButton].Flags & (4 << aIndex)))
	{
		SDL_PrivateJoystickButton(aJoystick, CELL_Video.Pads.ButtonMap[aButton].Joystick, SDL_PRESSED);
	}
	/* If the button is now up */
	else if(!aNew && (CELL_Video.Pads.ButtonMap[aButton].Flags & (4 << aIndex)))
	{
		SDL_PrivateJoystickButton(aJoystick, CELL_Video.Pads.ButtonMap[aButton].Joystick, SDL_RELEASED);
	}

	/* Update the status */
	CELL_Video.Pads.ButtonMap[aButton].Flags = (CELL_Video.Pads.ButtonMap[aButton].Flags & (~(4 << aIndex))) | (aNew ? (4 << aIndex) : 0);
}

/* Enter joystick mode */
#ifndef CELL_NO_SOFT_INPUT
void							CELL_PAD_JOYSTICK_Enter				(enum PadMode aOldMode)
{
	/* Nothing */
}

/* Release all buttons*/
void							CELL_PAD_JOYSTICK_Exit				(enum PadMode aNewMode)
{
	if(CELL_Video.Pads.Pads[0].Open && CELL_Video.Pads.Pads[0].Joystick)
	{
		for(int i = 0; i != NUM_BUTTONS; i ++)
		{
			ProcessJoystickButton(CELL_Video.Pads.Pads[0].Joystick, 0, i, 0, 1);
		}

		for(int i = 0; i != NUM_AXES; i ++)
		{
			SDL_PrivateJoystickAxis(CELL_Video.Pads.Pads[0].Joystick, i, 0);
		}
	}
}
#endif

/* Process all buttons and axes, called by SDL_Joystick code not by the SDL_Video */
void							CELL_PAD_JOYSTICK_Process			(SDL_Joystick* aJoystick, uint32_t aIndex)
{
#ifndef CELL_NO_SOFT_INPUT
	if(aIndex < NUM_PADS && CELL_Video.Pads.Pads[aIndex].Open && CELL_Video.Pads.Pads[aIndex].Mode == JOYSTICK)
#else
	if(aIndex < NUM_PADS && CELL_Video.Pads.Pads[aIndex].Open)
#endif
	{
		CellPadData newpadstate;
		if((CELL_OK == cellPadGetData(aIndex, &newpadstate)) && (newpadstate.len >= 8))
		{
			uint32_t newbuttons = newpadstate.button[2] | (newpadstate.button[3] << 8);

			/* Process buttons */
			if(newbuttons != CELL_Video.Pads.Pads[aIndex].OldButtons)
			{
				for(int i = 0; i != NUM_BUTTONS; i ++)
				{
					ProcessJoystickButton(aJoystick, aIndex, i, newbuttons & (1 << i), CELL_Video.Pads.Pads[aIndex].OldButtons & (1 << i));
				}

				CELL_Video.Pads.Pads[aIndex].OldButtons = newbuttons;
			}

			/* Process Axes */
			for(int i = 0; i != NUM_AXES; i ++)
			{
				if(CELL_Video.Pads.Pads[aIndex].OldAxes[i] != newpadstate.button[AxisIndex[i]])
				{
					int16_t value = (newpadstate.button[AxisIndex[i]] - 0x80) * 256;
					SDL_PrivateJoystickAxis(aJoystick, i, value);
				}
			}

			for(int i = 0; i != NUM_AXES; i ++)
			{
				CELL_Video.Pads.Pads[aIndex].OldAxes[i] = newpadstate.button[AxisIndex[i]];
			}
		}
	}

	return;
}

